package ltd.ninefish.framework.mybatisplus.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author zhaoxiubin
 * create-time 2023-12-17 13:42
 * description DTO服务基类（ 泛型：T 是实体，D 是DTO对象）
 **/

public interface DtoBaseService<T, D> extends IService<T> {
    /**
     * 获取 DTO 的 class
     * @return {@link Class<D>}
     */
    Class<D> getDtoClass();

    /**
     * 根据params获取QueryWrapper
     * @param params
     * @return
     */
    QueryWrapper<T> getWrapper(QueryWrapper<T> queryWrapper, Map<String, Map<String, Object>> params);

    /**
     * 插入一条记录（选择字段，策略插入）
     * @param dto DTO对象
     * @return 创建结果
     */
    boolean create(D dto);

    /**
     * 插入（批量）
     * @param dtoList DTO对象对象集合
     * @return 创建结果
     */
    @Transactional(rollbackFor = Exception.class)
    boolean createBatch(Collection<D> dtoList);

    /**
     * 插入（批量）
     *
     * @param dtoList DTO对象对象集合
     * @param batchSize  插入批次数量
     * @return 创建结果
     */
    boolean createBatch(Collection<D> dtoList, int batchSize);

    /**
     * 批量修改插入
     *
     * @param dtoList DTO对象对象集合
     * @return 创建或更新结果
     */
    @Transactional(rollbackFor = Exception.class)
    boolean createOrModifyBatch(Collection<D> dtoList);

    /**
     * 批量修改插入
     *
     * @param dtoList DTO对象集合
     * @param batchSize  每次的数量
     * @return 创建或更新结果
     */
    boolean createOrModifyBatch(Collection<D> dtoList, int batchSize);

    /**
     * TableId 注解存在更新记录，否插入一条记录
     *
     * @param dto DTO对象
     */
    boolean createOrModify(D dto);

    /**
     * 根据实体(ID)删除
     *
     * @param dto DTO对象
     * @return 删除结果
     */
    boolean deleteById(D dto);

    /**
     * 根据 ID 选择修改
     *
     * @param dto DTO对象
     */
    boolean modifyById(D dto);

    /**
     * 根据ID 批量更新
     *
     * @param dtoList DTO对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    boolean modifyBatchById(Collection<D> dtoList);

    /**
     * 根据ID 批量更新
     *
     * @param dtoList DTO对象集合
     * @param batchSize  更新批次数量
     */
    boolean modifyBatchById(Collection<D> dtoList, int batchSize);

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    D queryById(Serializable id);

    /**
     * 根据 ID 查询，返回一个Option对象
     *
     * @param id 主键ID
     * @return {@link Optional}
     */
    default Optional<D> queryOptById(Serializable id){
        return Optional.ofNullable(queryById(id));
    }

    /**
     * 查询（根据ID 批量查询）
     *
     * @param idList 主键ID列表
     */
     List<D> queryByIds(Collection<? extends Serializable> idList);


    /**
     * 查询（根据 columnMap 条件）
     *
     * @param columnMap 表字段 map 对象
     */
     List<D> queryByMap(Map<String, Object> columnMap);

    /**
     * 根据 Wrapper，查询一条记录 <br/>
     * <p>结果集，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    D queryOne(Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper，查询一条记录 <br/>
     * <p>结果集，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @return {@link Optional} 返回一个Optional对象
     */
     Optional<D> queryOneOpt(Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper，查询一条记录
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @param throwEx      有多个 result 是否抛出异常
     */
    D queryOne(Wrapper<T> queryWrapper, boolean throwEx);

    /**
     * 根据 Wrapper，查询一条记录
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @param throwEx      有多个 result 是否抛出异常
     * @return {@link Optional} 返回一个Optional对象
     */
    Optional<D> queryOneOpt(Wrapper<T> queryWrapper, boolean throwEx);

    /**
     * 查询所有
     *
     * @see Wrappers#emptyWrapper()
     */
    default List<D> getList() {
        return getList(Wrappers.emptyWrapper());
    }

    /**
     * 查询列表
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    List<D> getList(Wrapper<T> queryWrapper);
}
